#!/usr/bin/python3
# -*- coding:utf-8 -*-
import os
import sys
import logging
import numpy as np

LOSS        = 2e-3
MINIMUM     = 10e-10
REDUCTION   = 0       # <<< 手动改：0 逐元素，1 只比第一个值

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s'
)


def verify_first_only(real_path, golden_path):
    real = np.fromfile(real_path, dtype=np.float32)[0]
    golden = np.fromfile(golden_path, dtype=np.float32)[0]
    abs_err = abs(real - golden)
    rel_err = abs_err / (abs(golden) + MINIMUM)
    logging.info(f"First value  real : {real}")
    logging.info(f"First value golden: {golden}")
    if abs_err <= LOSS and rel_err <= LOSS:
        logging.info("FIRST VALUE: PASS — within tolerance.")
        sys.exit(0)
    else:
        logging.error("FIRST VALUE: FAIL — out of tolerance.")
        logging.error(f"abs_err = {abs_err}, rel_err = {rel_err}")
        sys.exit(1)


def verify_all(real_path, golden_path):
    real = np.fromfile(real_path, dtype=np.float32)
    golden = np.fromfile(golden_path, dtype=np.float32)
    if real.shape != golden.shape:
        logging.error(f"Shape mismatch: real {real.shape} vs golden {golden.shape}")
        sys.exit(1)
    abs_err = np.abs(real - golden)
    rel_err = abs_err / (np.abs(golden) + MINIMUM)
    pass_mask = (abs_err <= LOSS) & (rel_err <= LOSS)
    if np.all(pass_mask):
        logging.info("ALL ELEMENTS: PASS — within tolerance.")
        sys.exit(0)
    else:
        bad_idx = np.where(~pass_mask)[0]
        logging.error(f"ELEMENTS FAIL: {len(bad_idx)} / {real.size}")
        for i in bad_idx[:10]:
            logging.error(f"Idx {i}: real={real[i]}, golden={golden[i]}, "
                         f"abs_err={abs_err[i]}, rel_err={rel_err[i]}")
        sys.exit(1)


def main():
    if len(sys.argv) != 3:
        logging.error("Usage: python verify.py <real_result.bin> <golden.bin>")
        sys.exit(1)

    logging.info(f"REDUCTION = {REDUCTION}  (0=all, 1=first)")
    if REDUCTION == 0:
        verify_all(sys.argv[1], sys.argv[2])
    else:
        verify_first_only(sys.argv[1], sys.argv[2])


if __name__ == '__main__':
    main()